package analiseSintatica.Regras.Comandos;

import java.util.LinkedList;
import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;

public class RegraCmd extends Regra {

    protected String estrutura = "<cmd> ::= <if> | <while> | <do_while> | <return> | <for> | <printf> | <scanf>";


    protected static Regra instancia;

    

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraCmd() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraCmd getInstance() {
        if (instancia == null) {
            instancia = new RegraCmd();
        }
        return (RegraCmd) instancia;
    }

    

    @Override
    public NoArvore analisar(LinkedList<LinkToken> tokens) throws ErroSintaticoException {

        ErroSintaticoException erros = new ErroSintaticoException();

        NoArvore naoterminalcmd = new NoArvore("cmd", false);
        //if(tokens.getFirst().getToken().equals("if")))

        if (RegraIf.getInstance().getPrimeiro().contains(tokens.getFirst().getLexema())) {

            try {
                naoterminalcmd.adicionaFilho(RegraIf.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }

        } else if (RegraWhile.getInstance().getPrimeiro().contains(tokens.getFirst().getLexema())) {

            try {
                naoterminalcmd.adicionaFilho(RegraWhile.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }

        } else if (listaContem(RegraDoWhile.getInstance().getPrimeiro(), tokens.getFirst())) {

            try {
                naoterminalcmd.adicionaFilho(RegraDoWhile.getInstance() .analisar(tokens));

            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }

        } else if (listaContem(RegraReturn.getInstance().getPrimeiro(), tokens.getFirst())) {

            try {
                naoterminalcmd.adicionaFilho(RegraReturn.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }

        } else if (listaContem(RegraFor.getInstance().getPrimeiro(), tokens.getFirst())) {

            try {
                naoterminalcmd.adicionaFilho(RegraFor.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }

        } else if (listaContem(RegraPrintf.getInstance().getPrimeiro(), tokens.getFirst())) {

            try {
                naoterminalcmd.adicionaFilho(RegraPrintf.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }

        } else if (listaContem(RegraScanf.getInstance().getPrimeiro(), tokens.getFirst())) {

            try {
                naoterminalcmd.adicionaFilho(RegraScanf.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {

                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }
        }

        return naoterminalcmd;
    }

    

    @Override
    protected void setPrimeiro() {

        this.primeiro.add("if");
        this.primeiro.add("while");
        this.primeiro.add("do");
        this.primeiro.add("return");
        this.primeiro.add("for");
        this.primeiro.add("printf");
        this.primeiro.add("scanf");

//        primeiro = getUniao(primeiro, RegraIf.getInstance().getPrimeiro());
//        primeiro = getUniao(primeiro, RegraWhile.getInstance().getPrimeiro());
//        primeiro = getUniao(primeiro, RegraDoWhile.getInstance().getPrimeiro());
//        primeiro = getUniao(primeiro, RegraReturn.getInstance().getPrimeiro());
//        primeiro = getUniao(primeiro, RegraFor.getInstance().getPrimeiro());
//        primeiro = getUniao(primeiro, RegraPrintf.getInstance().getPrimeiro());
//        primeiro = getUniao(primeiro, RegraScanf.getInstance().getPrimeiro());
    }

    @Override
    protected void setSeguinte() {
        seguinte = RegraInstrucao.getInstance().getSeguinte();
    }
}
